package fag.editor;

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

import fag.core.model.Animation;
import fag.core.model.Frame;
import fag.core.model.Model;

public class ModelEditor extends JFrame implements ActionListener,ComponentListener {

	private static final long serialVersionUID = -6022432516976544716L;
	
	// Composants de l'editeur
	private FrameModifier frameModifier = new FrameModifier();
	private AnimationModifier animationModifier = new AnimationModifier();
	private ModelBar modelBar = new ModelBar();
	private Timeline timeline = new Timeline();
	private ResourceLoader resourceLoader = new ResourceLoader(System.getProperty("user.dir")+"/src/imgs/arkanoid/rackets/");
	private ShapeChooser shapeChooser = new ShapeChooser();
	private ModeChooser modeChooser = new ModeChooser();
	private ZoomChooser zoomChooser = new ZoomChooser();
	private FrameEditor frameEditor = new FrameEditor();
	private AnimationPlayer animationPlayer;
	
	// Partie nord de l'editeur
	private JPanel pNorth = new JPanel(new GridLayout(3,1));
	private JPanel pModifier = new JPanel();
	private JPanel pChooser = new JPanel();
	private JScrollPane spTimeline = new JScrollPane(timeline);
	
	// Modele
	private Model model;
	private int currentAnimation;
	private int currentFrame;
	
	// Outils
	private Serializer serializer = new Serializer();
	JFileChooser fileChooser = new JFileChooser();
	

	
	public static void main(String[] args) {
		
		ModelEditor editor = new ModelEditor();
	}
	
	public ModelEditor() {
	
		setTitle("EditorV2");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
		
		pModifier.add(animationModifier);
		pModifier.add(frameModifier);
		
		pChooser.add(shapeChooser);
		pChooser.add(modeChooser);
		//pChooser.add(zoomChooser);
		
		pNorth.add(pModifier);
		pNorth.add(spTimeline);
		pNorth.add(pChooser);
		
		add(pNorth,BorderLayout.NORTH);
		add(resourceLoader,BorderLayout.EAST);
		add(frameEditor,BorderLayout.CENTER);
		setJMenuBar(modelBar);
		
		frameModifier.addActionListener(this);
		animationModifier.addActionListener(this);
		modelBar.addActionListener(this);
		timeline.addActionListener(this);
		resourceLoader.addActionListener(this);
		shapeChooser.addActionListener(this);
		modeChooser.addActionListener(this);
		//zoomChooser.addActionListener(this);
		frameEditor.addActionListener(this);
		
		addComponentListener(this);
		
		newModel();
		pack();
		frameEditor.updateCenter();
		timeline.updateWidth();
		shapeChooser.setClickAction(false);
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		
		if(e.getSource() == frameModifier) {
			
			if(e.getActionCommand() == FrameModifier.ACTION_ADD_FRAME) {
				
				model.getListAnimation().get(currentAnimation).addFrame(new Frame());
				timeline.updateWidth();
				repaint();
			}
			
			if(e.getActionCommand() == FrameModifier.ACTION_REMOVE_FRAME) {
				
				if(model.getListAnimation().get(currentAnimation).getListFrame().size() != 1) {
					
					model.getListAnimation().get(currentAnimation).removeFrame(currentFrame);
					timeline.setAnimation(model.getListAnimation().get(currentAnimation));
					currentFrame = 0;
					frameEditor.setFrame(model.getListAnimation().get(currentAnimation).getListFrame().get(currentFrame));
					repaint();
				}
			}
			
			if(e.getActionCommand() == FrameModifier.ACTION_DURATION_CHANGED) {
				
				if(frameModifier.getCurrentDuration() >= 0) {
					
				model.getListAnimation().get(currentAnimation).getListFrame().get(currentFrame).setDuration(frameModifier.getCurrentDuration());
				timeline.updateWidth();
				repaint();
				}
			}
		}
		
		if(e.getSource() == animationModifier) {	
			
			if(e.getActionCommand() == AnimationModifier.ACTION_ADD_ANIMATION) {
				
				String nom = obtainAnimationName();
				
				if(nom != null) {
					
					if(!nom.equals("")) {
						
						model.getListAnimation().add(new Animation(nom));
						model.getListAnimation().get(model.getListAnimation().size()-1).addFrame(new Frame());
						animationModifier.setModel(model);
					}
					else 
						wrongAnimationName();
				}	
			}
			
			if(e.getActionCommand() == AnimationModifier.ACTION_PLAY_ANIMATION) {
				
				animationPlayer = new AnimationPlayer(model.getListAnimation().get(currentAnimation));
			}
			
			if(e.getActionCommand() == AnimationModifier.ACTION_REMOVE_ANIMATION) {		
				
				if(model.getListAnimation().size() != 1) {
					
					model.getListAnimation().remove(currentAnimation);
					animationModifier.setModel(model);
					repaint();
				}
			}
			
			if(e.getActionCommand() == AnimationModifier.ACTION_RENAME_ANIMATION) {
				
				String nom = obtainAnimationName();
				
				if(nom != null) {
					
					if(!nom.equals("")) {
						
						model.getListAnimation().get(currentAnimation).setName(nom);
						animationModifier.setModel(model);
					}
				}
			}
			
			if(e.getActionCommand() == AnimationModifier.ACTION_SELECTION_ANIMATION_CHANGED) {
				
				currentAnimation = animationModifier.getCurrentAnimationIndex();
				currentFrame = 0;
				timeline.setAnimation(model.getListAnimation().get(currentAnimation));
				frameEditor.setFrame(model.getListAnimation().get(currentAnimation).getListFrame().get(currentFrame));
				frameModifier.setCurrentDuration(model.getListAnimation().get(currentAnimation).getListFrame().get(currentFrame).getDuration());
				spTimeline.updateUI();
				repaint();
			}
		}
		
		if(e.getSource() == shapeChooser) {
			
			if(e.getActionCommand() == ShapeChooser.ACTION_CHANGED_SHAPE) {
				
					frameEditor.setShape(shapeChooser.getCurrentShape());
			}
		}
		
		if(e.getSource() == modeChooser) {
			
			if(e.getActionCommand() == ModeChooser.ACTION_CHANGED_MODE) {	
				
				frameEditor.setMode(modeChooser.getCurrentMode());
				shapeChooser.resetSelection();
				shapeChooser.setClickAction(false);
				
				if(modeChooser.getCurrentMode().equals("Hitbox")) {
					
					shapeChooser.setClickAction(true);
				}
			}
		}
		
		if(e.getSource() == zoomChooser) {
			
			// A implementer
		}
		
		if(e.getSource() == modelBar) {
			
			if(e.getActionCommand() == ModelBar.ACTION_LOAD_MODEL) {
				
				loadModel();
				repaint();
			}
			
			if(e.getActionCommand() == ModelBar.ACTION_SAVE_MODEL) {
				
				saveModel();
			}
			
			if(e.getActionCommand() == ModelBar.ACTION_NEW_MODEL) {
				
				newModel();
				repaint();
			}
		}
		
		if(e.getSource() == timeline) {	
			
			if(e.getActionCommand() == Timeline.ACTION_SELECTION_FRAME_CHANGED) {
				
				currentFrame = timeline.getCurrentFrameIndex();
				frameEditor.setFrame(model.getListAnimation().get(currentAnimation).getListFrame().get(currentFrame));
				frameModifier.setCurrentDuration(model.getListAnimation().get(currentAnimation).getListFrame().get(currentFrame).getDuration());
				shapeChooser.resetSelection();
				modeChooser.resetSelection();
				repaint();
			}
		}
		
		if(e.getSource() == resourceLoader) {
			
			if(e.getActionCommand() == ResourceLoader.ACTION_LOAD_IMAGE) {
				
				BufferedImage bi = loadImage();
				
				if(bi != null)
					frameEditor.setBufferedImage(bi);
				repaint();
			}
		}
		
		if(e.getSource() == frameEditor) {
			
			if(e.getActionCommand() == FrameEditor.ACTION_REPAINT_NEEDED) {
				
				repaint();
			}		
			
			if(e.getActionCommand() == FrameEditor.ACTION_RESET_SHAPE_SELECTION) {
				
				shapeChooser.resetSelection();
				repaint();
			}
		}
		
		if(e.getSource() == zoomChooser) {
			
			if(e.getActionCommand() == ZoomChooser.ACTION_CHANGED_ZOOM) {
				
				frameEditor.setZoom(zoomChooser.getCurrentZoom());
				repaint();
			}
		}
	}
	
	private void newModel() {
		
		model = new Model();
		model.getListAnimation().add(new Animation("default"));
		model.getListAnimation().get(0).addFrame(new Frame());
		currentAnimation = 0;
		currentFrame = 0;
		animationModifier.setModel(model);
		timeline.setAnimation(model.getListAnimation().get(0));
		frameEditor.setFrame(model.getListAnimation().get(0).getListFrame().get(0));
		frameModifier.setCurrentDuration(0);	
	}
	
	private void saveModel() {
		
		String myFile = explorer("Save");
		
		try{
			for(Animation a : model.getListAnimation()) {
				
				a.updateDuration();
				
				for(Frame f : a.getListFrame()) {
					
					f.updateBounds();
				}
			}
			serializer.Serialize(model,myFile);
		}catch(NullPointerException e){
			System.out.println("Le nom du fichier est manquant.");
		}
	}
	
	public void loadModel() {
		
		String myFile = explorer("Load");
		
		try{
		model = (Model) serializer.Deserialize(myFile);
		}catch(NullPointerException e){
			System.out.println("Aucun fichier sélectionné.");}
		currentAnimation = 0;
		currentFrame = 0;
		animationModifier.setModel(model);
		timeline.setAnimation(model.getListAnimation().get(0));
		frameEditor.setFrame(model.getListAnimation().get(0).getListFrame().get(0));
		frameModifier.setCurrentDuration(model.getListAnimation().get(0).getListFrame().get(0).getDuration());
	}
	
	private BufferedImage loadImage() {
		
		BufferedImage i = null;
		try {
			i = ImageIO.read(new File(resourceLoader.getImageURL()));
			}
		catch (IOException exception) {
			exception.printStackTrace();
			}
		return i;
	}
	
	public String explorer(String s) {
		
		String approve = new String(s);
		fileChooser.setCurrentDirectory(new File("."));
		int result = fileChooser.showDialog(fileChooser,approve);
		String myFile = null;
		
		if(result == JFileChooser.APPROVE_OPTION) {
			
			myFile = new String(fileChooser.getSelectedFile().toString());
		}
		return myFile;
	}
	
	public String obtainAnimationName() {
		
		return JOptionPane.showInputDialog(null, "Nom de l'Animation ?", "Popup Editor", JOptionPane.QUESTION_MESSAGE);
	}
	
	public void wrongAnimationName() {
		
		JOptionPane.showMessageDialog(null, "Nom de l'animation non saisi !", "Editor Popup", JOptionPane.ERROR_MESSAGE);
	}

	@Override
	public void componentHidden(ComponentEvent e) {}

	@Override
	public void componentMoved(ComponentEvent e) {}

	@Override
	public void componentResized(ComponentEvent e) {
		
		frameEditor.updateCenter();
		repaint();
	}

	@Override
	public void componentShown(ComponentEvent e) {}
}